package com.chengzheng.crawler.spiderman.work.runner;

/**
 * @author zhengcheng
 * @date 2018/1/30
 * @time 下午5:38
 * @email chengzhengzheng@meituan.com
 **/


import com.chengzheng.crawler.spiderman.config.ConfigUtils;
import com.chengzheng.crawler.spiderman.work.WorkerManager;
import com.chengzheng.crawler.spiderman.work.download.FetchManager;
import com.chengzheng.crawler.spiderman.work.extract.ExtractorManager;
import com.chengzheng.crawler.spiderman.work.save.SaveManager;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
 * @author zhengcheng
 * @date 2018/1/30
 * @time 下午5:38
 * @email chengzhengzheng@meituan.com
 **/



/**
 * 爬虫上下文
 */
public class Context {

    private static final Logger LOGGER = LoggerFactory.getLogger(Context.class);


    /**
     * 构建工作管理单元
     */
    public Context() {

        this.workerManagers = new ArrayList<>();


        //构建下载管理器
        final int downloadWorkerSize = ConfigUtils.getDownloadWorkerSize();
        FetchManager fetchManager = new FetchManager(downloadWorkerSize);
        this.addWorkerManager(fetchManager);
        LOGGER.debug("构建下载管理器");

        //构建解析管理器
        final int extractSize = ConfigUtils.getExtractorWorkerSize();
        ExtractorManager extractorManager = new ExtractorManager(extractSize);
        this.addWorkerManager(extractorManager);
        LOGGER.debug("构建解析管理器");


        //构建save管理器
        final int saveWorkerSize = ConfigUtils.getSaveWorkerSize();
        SaveManager saveManager = new SaveManager(saveWorkerSize);
        this.addWorkerManager(saveManager);
        LOGGER.debug("构建保存管理器");


        ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("crawler-worker-%d").build();
        this.threads = new ThreadPoolExecutor(workerManagers.size(), 200, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy());


    }

    /**
     * 工作管理者集合
     */
    private List<WorkerManager> workerManagers;

    private ExecutorService threads;

    public Context addWorkerManager(WorkerManager manager) {
        this.workerManagers.add(manager);
        return this;
    }


    public void start() {
        //启动各个工头
        LOGGER.debug("开始行动...");

        this.workerManagers.forEach(m -> threads.execute(m));
    }


}
